﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;

namespace ARDrone2
{
    /// <summary>
    /// Global communication tunnel between local machine and the AR.Drone.
    /// </summary>
    public static class CommunicationChannel
    {
        /// <summary>
        /// Hostname of the drone.
        /// </summary>
        private const string _DroneHostname = "192.168.1.1";

        /// <summary>
        /// Port of AT command channel.
        /// </summary>
        private const int _ATCommandPort = 5556;

        /// <summary>
        /// Port of navigation data channel.
        /// </summary>
        private const int _NavigationDataPort = 5554;

        /// <summary>
        /// Port of video stream channel.
        /// </summary>
        private const int _VideoStreamPort = 5555;

        /// <summary>
        /// Port of critical data channel.
        /// </summary>
        private const int _ControlPort = 5559;

        /// <summary>
        /// Current sequence number of AT command.
        /// </summary>
        private static int _ATCommandSequenceNumber = 1;

        /// <summary>
        /// UDP client for AT command transmission.
        /// </summary>
        /// <remarks>
        /// Commands are to be sent on a regular basis (usually 30 times per second).
        /// </remarks>
        private static UdpClient _ucATCommand = new UdpClient();

        /// <summary>
        /// UDP client for navigation data transmission.
        /// </summary>
        /// <remarks>
        /// Data are sent approximatively 15 times per second in demo mode, and 200 
        /// times per second in full (debug) mode.
        /// </remarks>
        private static UdpClient _ucNavigationData = new UdpClient();

        /// <summary>
        /// TCP client for video stream transmission.
        /// </summary>
        /// <remarks>
        /// UDP for AR.Drone 1.0 , TCP for AR.Drone 2.0.
        /// </remarks>
        private static TcpClient _tcVideoStream = new TcpClient();

        /// <summary>
        /// TCP client for critical data transmission. It is used to retrieve 
        /// configuration data, and to acknowledge important information such as the 
        /// sending of configuration information.
        /// </summary>
        private static TcpClient _tcControl = new TcpClient();

        /// <summary>
        /// Get the next sequence number of AT command.
        /// </summary>
        /// <returns>The next sequence number of AT command.</returns>
        public static int GetNextATCommandSequenceNumber()
        {
            return _ATCommandSequenceNumber++;
        }

        /// <summary>
        /// Reset the sequence number of AT command.
        /// </summary>
        public static void ResetATCommandSequenceNumber()
        {
            _ATCommandSequenceNumber = 1;
        }

        /// <summary>
        /// Send AT command to the drone.
        /// </summary>
        /// <param name="cmdstr">Command string to send.</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        /// <exception cref="System.ArgumentOutOfRangeException"></exception>
        /// <exception cref="System.Net.Sockets.SocketException"></exception>
        public static void SendATCommand(string cmdstr)
        {
            if (cmdstr == null) throw new ArgumentNullException("cmdstr", "The argument cannot be null.");
            if (cmdstr.Length > 1024) throw new ArgumentOutOfRangeException("cmdstr", "The maximum AT command length is 1024.");

            // Convert the command string to bytes
            byte[] cmdbyte = Encoding.ASCII.GetBytes(cmdstr);

            // Send the command
            _ucATCommand.Send(cmdbyte, cmdbyte.Length, _DroneHostname, _ATCommandPort);
        }
    }
}
